www.gusucode.com > VC 模范QQ做的一个界面-源码程序 > VC 模范QQ做的一个界面-源码程序/code/MyQQ/TreeCtrlST.cpp

    //Download by http://www.NewXing.com
// TreeCtrlST.cpp : implementation file
//

#include "stdafx.h"
#include "MyQQ.h"
#include "TreeCtrlST.h"
#include "windowsx.h"  // required for GET_X_LPARAM, GET_Y_LPARAM)


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTreeCtrlST

CTreeCtrlST::CTreeCtrlST()
{
	BgColor = RGB(255, 255, 255);
	FontColor = RGB(0, 0, 0);
	m_bBgStretch = FALSE;

}

CTreeCtrlST::~CTreeCtrlST()
{
	if( m_bitmap.m_hObject != NULL )
		m_bitmap.DeleteObject();
	if( m_pal.m_hObject != NULL )
		m_pal.DeleteObject();
}


BEGIN_MESSAGE_MAP(CTreeCtrlST, CTreeCtrl)
	//{{AFX_MSG_MAP(CTreeCtrlST)
	ON_WM_DRAWITEM()
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_PALETTECHANGED()
	ON_WM_SIZE()
	ON_WM_QUERYNEWPALETTE()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOVING()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeCtrlST message handlers



void CTreeCtrlST::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	// TODO: Add your message handler code here and/or call default
	
	CTreeCtrl::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

BOOL CTreeCtrlST::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	if( m_bitmap.m_hObject != NULL )
		return TRUE;
	return CTreeCtrl::OnEraseBkgnd(pDC);
}

void CTreeCtrlST::DrawItemText(CDC *pDC, CString text, CRect rect, int nFormat)
{
		UINT nStyle = DT_VCENTER | DT_SINGLELINE;
	if (nFormat == LVCFMT_LEFT)
		nStyle |= DT_LEFT;
	else if (nFormat == LVCFMT_CENTER)
		nStyle |= DT_CENTER;
	else // nFormat == LVCFMT_RIGHT
		nStyle |= DT_RIGHT;

	if((text.GetLength()>0) && (rect.right>rect.left))
	{
		pDC->DrawText (text, rect, nStyle);
	}
}

void CTreeCtrlST::OnItemexpanding(NMHDR *pNMHDR, LRESULT *pResult)
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	if( m_bitmap.m_hObject != NULL )
		InvalidateRect(NULL);

	*pResult = 0;
}

void CTreeCtrlST::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
		
	CRect rcClip, rcClient;
	dc.GetClipBox( &rcClip );
	GetClientRect(&rcClient);

	// Create a compatible memory DC 
	CDC memDC;
	memDC.CreateCompatibleDC( &dc );
	
	// Select a compatible bitmap into the memory DC
	CBitmap bitmap, bmpImage;
	bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );
	CBitmap *OldBitmap = memDC.SelectObject( &bitmap );

	// First let the control do its default drawing.
	CTreeCtrl::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 );


/*
	// create the font
	CFont *pFontDC;
	CFont fontDC, boldFontDC;
	LOGFONT logfont;

	CFont *pFont = GetFont();
	pFont->GetLogFont( &logfont );

	fontDC.CreateFontIndirect( &logfont );		//普通字体
	pFontDC = memDC.SelectObject( &fontDC );

	logfont.lfWeight = 700;
	boldFontDC.CreateFontIndirect( &logfont );	//粗体字

	// and now let's get to the painting itself
	HTREEITEM hItem = GetFirstVisibleItem();

	int n = GetVisibleCount();

	hItem = GetFirstVisibleItem();
	n = GetVisibleCount();

	while(hItem!=NULL && n>=0)
	{
		CRect rect;
		CRect m_labelRect;

		UINT selflag = TVIS_SELECTED ; // |TVIS_DROPHILITED;
	
		CString ItemText = GetItemText(hItem);

		GetItemRect( hItem, &m_labelRect, TRUE );	//文字
		GetItemRect( hItem, &rect, FALSE );

		if ( !(GetItemState( hItem, selflag ) & selflag )) //选中状态
		{
			memDC.SetBkMode(TRANSPARENT);

			memDC.SetTextColor(::GetSysColor (COLOR_WINDOWTEXT ));

			DrawItemText(&memDC,ItemText,m_labelRect,LVCFMT_LEFT);
		}
		else
		{
			COLORREF m_highlightColor = ::GetSysColor (COLOR_HIGHLIGHT);

			CBrush brush(m_highlightColor);

			memDC.FillRect (m_labelRect, &brush);
			// draw a dotted focus rectangle
			memDC.DrawFocusRect (m_labelRect);

			memDC.SetBkColor(m_highlightColor);

			memDC.SetTextColor(::GetSysColor (COLOR_HIGHLIGHTTEXT));

			memDC.SelectObject( &boldFontDC );

			DrawItemText(&memDC,ItemText,m_labelRect,LVCFMT_LEFT);

			memDC.SelectObject( &pFontDC );
		}

		hItem = GetNextVisibleItem( hItem );
		n--;
	}

	memDC.SelectObject( pFontDC );

*/

	// Draw bitmap in the background if one has been set
	if( m_bitmap.m_hObject != NULL )
	{
		// Now create a mask
		CDC maskDC;
		maskDC.CreateCompatibleDC(&dc);
		CBitmap maskBitmap;

		// Create monochrome bitmap for the mask
		maskBitmap.CreateBitmap( rcClient.Width(), rcClient.Height(), 
					1, 1, NULL );

		CBitmap *OldMask = maskDC.SelectObject( &maskBitmap );
		memDC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) );

		// Create the mask from the memory DC
		maskDC.BitBlt( 0, 0, 
			rcClient.Width(), rcClient.Height(), 
			&memDC, 
			rcClient.left, rcClient.top, 
			SRCCOPY );

		
		CDC tempDC;
		tempDC.CreateCompatibleDC(&dc);
		CBitmap *Oldtemp = tempDC.SelectObject( &m_bitmap );

		CDC imageDC;
		CBitmap bmpImage;
		imageDC.CreateCompatibleDC( &dc );

		bmpImage.CreateCompatibleBitmap( &dc, rcClient.Width(), 
						rcClient.Height() );
		CBitmap *OldImage = imageDC.SelectObject( &bmpImage );

		if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
		{
			dc.SelectPalette( &m_pal, FALSE );
			dc.RealizePalette();

			imageDC.SelectPalette( &m_pal, FALSE );
		}

		// Get x and y offset
		CRect rcRoot;
		GetItemRect(GetRootItem(), rcRoot, FALSE );
		rcRoot.left = -GetScrollPos( SB_HORZ );

		imageDC.FillSolidRect(CRect(0,0,rcClient.right,rcClient.bottom),BgColor);

		if( m_bBgStretch )
		{
			imageDC.SetStretchBltMode(COLORONCOLOR);
			imageDC.StretchBlt(
				0,0,rcClient.right,rcClient.bottom,
				&tempDC,
				0,0,m_cxBitmap,m_cyBitmap,
				SRCCOPY
			);
		}
		else
		{	
			imageDC.BitBlt( 
				rcClient.right-m_cxBitmap,rcClient.bottom-m_cyBitmap,
				m_cxBitmap,m_cyBitmap,
				&tempDC,
				0, 0, 
				SRCCOPY );
			/*
			// Draw bitmap in tiled manner to imageDC
			for( int i = rcRoot.left; i < rcClient.right; i += m_cxBitmap )
			for( int j = rcRoot.top; j < rcClient.bottom; j += m_cyBitmap )
			{
				imageDC.BitBlt( i, j, m_cxBitmap, m_cyBitmap, 
					&tempDC,0, 0, SRCCOPY );
			}
			*/
		}
		
		// Set the background in memDC to black. Using SRCPAINT with black and any other
		// color results in the other color, thus making black the transparent color
		memDC.SetBkColor(RGB(0,0,0));        
		memDC.SetTextColor(RGB(255,255,255));

		memDC.BitBlt(	rcClip.left, rcClip.top, 
				rcClip.Width(), rcClip.Height(), 
				&maskDC, 
				rcClip.left, rcClip.top, 
				SRCAND);

		// Set the foreground to black. See comment above.
		imageDC.SetBkColor(RGB(255,255,255));
		imageDC.SetTextColor(RGB(0,0,0));

		imageDC.BitBlt(	rcClip.left, rcClip.top, 
				rcClip.Width(), rcClip.Height(), 
				&maskDC, 
				rcClip.left, rcClip.top, 
				SRCAND);

		// Combine the foreground with the background
		imageDC.BitBlt(	rcClip.left, rcClip.top, 
				rcClip.Width(), rcClip.Height(), 
				&memDC, 
				rcClip.left, rcClip.top,
				SRCPAINT);
		
		// Draw the final image to the screen		
		dc.BitBlt(	rcClip.left, rcClip.top, 
				rcClip.Width(), rcClip.Height(), 
				&imageDC, 
				rcClip.left, rcClip.top, SRCCOPY );

		//释放对象
		maskDC.SelectObject(OldMask);
		imageDC.SelectObject(OldImage);
		tempDC.SelectObject(Oldtemp);

		maskBitmap.DeleteObject();
		bmpImage.DeleteObject();

		maskDC.DeleteDC();
		imageDC.DeleteDC();
		tempDC.DeleteDC();
	}
	else
	{
		dc.BitBlt(	rcClip.left, rcClip.top, 
				rcClip.Width(), 
				rcClip.Height(), 
				&memDC, 
				rcClip.left, rcClip.top, SRCCOPY );
	}

	memDC.SelectObject(OldBitmap);
	bitmap.DeleteObject();
	memDC.DeleteDC();
	// Do not call CTreeCtrl::OnPaint() for painting messages
}

void CTreeCtrlST::OnPaletteChanged(CWnd* pFocusWnd) 
{
	CTreeCtrl::OnPaletteChanged(pFocusWnd);
	
	// TODO: Add your message handler code here
	if( pFocusWnd == this )
		return;

	CTreeCtrl::OnPaletteChanged(pFocusWnd);
}

void CTreeCtrlST::OnSize(UINT nType, int cx, int cy) 
{
	CTreeCtrl::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	Invalidate();
}

void CTreeCtrlST::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	CTreeCtrl::PreSubclassWindow();
}

BOOL CTreeCtrlST::SetBkImage(HBITMAP hBmp)
{
		if( m_bitmap.m_hObject != NULL )
		m_bitmap.DeleteObject();
	if( m_pal.m_hObject != NULL )
		m_pal.DeleteObject();

	if( hBmp == NULL ) 
		return FALSE;

	m_bitmap.Attach( hBmp );
	BITMAP bm;
	m_bitmap.GetBitmap( &bm );
	m_cxBitmap = bm.bmWidth;
	m_cyBitmap = bm.bmHeight;


	// Create a logical palette for the bitmap
	DIBSECTION ds;
	BITMAPINFOHEADER &bmInfo = ds.dsBmih;
	m_bitmap.GetObject( sizeof(ds), &ds );

	int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount;

	// Create a halftone palette if colors > 256. 
	CClientDC dc(NULL);			// Desktop DC
	if( nColors > 256 )
		m_pal.CreateHalftonePalette( &dc );
	else
	{
		// Create the palette

		RGBQUAD *pRGB = new RGBQUAD[nColors];
		CDC memDC;
		memDC.CreateCompatibleDC(&dc);

		memDC.SelectObject( &m_bitmap );
		::GetDIBColorTable( memDC, 0, nColors, pRGB );

		UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
		LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

		pLP->palVersion = 0x300;
		pLP->palNumEntries = nColors;

		for( int i=0; i < nColors; i++)
		{
			pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
			pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
			pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
			pLP->palPalEntry[i].peFlags = 0;
		}

		m_pal.CreatePalette( pLP );

		delete[] pLP;
		delete[] pRGB;
	}
	Invalidate();

	return TRUE;
}

BOOL CTreeCtrlST::SetBkImage(LPCTSTR lpszResourceName)
{
	HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(), 
			lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION );
	
	return SetBkImage(hBmp);
}

BOOL CTreeCtrlST::SetBkImage(UINT nIDResource)
{
	return SetBkImage( (LPCTSTR)nIDResource );
}

void CTreeCtrlST::SetBgStretch(BOOL Flag)
{
	m_bBgStretch = Flag;
}

BOOL CTreeCtrlST::OnQueryNewPalette() 
{
	// TODO: Add your message handler code here and/or call default
	CClientDC dc(this);

	if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
	{
		dc.SelectPalette( &m_pal, FALSE );
		BOOL result = dc.RealizePalette();
		if( result )
			Invalidate();
		return result;
	}
	return CTreeCtrl::OnQueryNewPalette();
}

void CTreeCtrlST::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	if( m_bitmap.m_hObject != NULL )
		InvalidateRect(NULL);

	CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CTreeCtrlST::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	if( m_bitmap.m_hObject != NULL )
		InvalidateRect(NULL);

	CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}



BOOL CTreeCtrlST::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
/*	//把单击动作当做双击处理
	if(pMsg->message == WM_LBUTTONDOWN)
	{
		pMsg->message = WM_LBUTTONDBLCLK;
	}
*/
	return CTreeCtrl::PreTranslateMessage(pMsg);
}

void CTreeCtrlST::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

/*	DWORD dw = GetMessagePos();			// retrieve mouse cursor position when msg was sent
	CPoint pt(GET_X_LPARAM(dw), GET_Y_LPARAM(dw));  // ..and put into point structure
	ScreenToClient(&pt);

	UINT flags = 0;
	HTREEITEM it = HitTest(pt, &flags);				// See where the click was on
//	if(it != NULL && nFlag == TVHT_ONITEMSTATEICON)
	if(  //(flags & TVHT_ONITEMRIGHT) || (flags & TVHT_ONITEMINDENT) ||
	    (flags & TVHT_ONITEM))
	{
	//	HTREEITEM SelItem = GetSelectedItem();
	//	SetItemData(SelItem, DWORD(nFlag));
	//	GetItemData(SelItem);
		CString str = GetItemText(it);

		AfxMessageBox(str, MB_OK,0);
	}
*/
	*pResult = 0;

}

void CTreeCtrlST::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	UINT flags = 0;
	HTREEITEM item = HitTest(point, &flags);
	if(item != NULL && (flags & TVHT_ONITEM)) //&& !ItemHasChildren(item))
	{
		HTREEITEM itch = GetChildItem(item);
		if(itch == NULL)
		{
		//	SelectItem(item);
		//	CString str = GetItemText(item);
		//	HWND hWnd = ((CMyQQApp*)AfxGetApp())->m_MainDlg;
		//	::PostMessage(hWnd, WM_SHOWINFO, LPARAM(item), 0);
/*			CUserInfoDlg* pUserDlg; 
			pUserDlg = new CUserInfoDlg;
			pUserDlg->Create(IDD_INFORMATION, NULL);//GetParent());
			pUserDlg->m_ShowText.Format("昵称: %s",str);			
			pUserDlg->ShowWindow(SW_SHOW);
			
*/
		}
	}
	CTreeCtrl::OnLButtonDown(nFlags, point);
}

void CTreeCtrlST::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	UINT flags = 0;
	HTREEITEM item = HitTest(point, &flags);
	if(item != NULL && (flags & TVHT_ONITEM)) //&& !ItemHasChildren(item))
	{
		HTREEITEM itch = GetChildItem(item);
		if(itch == NULL)
		{
			SelectItem(item);
			CString str = GetItemText(item);
			HWND hWnd = ((CMyQQApp*)AfxGetApp())->m_MainDlg;
			::PostMessage(hWnd, WM_SHOWINFO, LPARAM(item), 0);
/*			CUserInfoDlg* pUserDlg; 
			pUserDlg = new CUserInfoDlg;
			pUserDlg->Create(IDD_INFORMATION, NULL);//GetParent());
			pUserDlg->m_ShowText.Format("昵称: %s",str);
			pUserDlg->ShowWindow(SW_SHOW);
*/
		}
	}
	CTreeCtrl::OnLButtonUp(nFlags, point);
}

void CTreeCtrlST::OnMoving(UINT fwSide, LPRECT pRect) 
{
	CTreeCtrl::OnMoving(fwSide, pRect);
	
	// TODO: Add your message handler code here
//	Invalidate();
}